package com.apikey.auth.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import java.time.LocalDateTime;

/**
 * API Key实体类
 * 表示系统中的API密钥信息
 *
 * @author API Key Framework
 * @version 1.0
 */
@Entity
@Table(name = "api_keys", indexes = {
        @Index(name = "idx_api_key", columnList = "api_key"),
        @Index(name = "idx_user_id", columnList = "user_id"),
        @Index(name = "idx_status", columnList = "status"),
        @Index(name = "idx_expiry_time", columnList = "expiry_time"),
        @Index(name = "idx_is_deleted", columnList = "is_deleted")
})
public class ApiKey {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false, length = 100)
    private String name;

    @Column(name = "api_key", nullable = false, unique = true, length = 64)
    private String keyValue;

    @Column(name = "permissions", columnDefinition = "TEXT")
    private String permissions;

    @Column(name = "status", nullable = false, length = 20)
    private String status = "ACTIVE";

    @Column(name = "daily_limit")
    private Integer dailyLimit;

    @Column(name = "monthly_limit")
    private Integer monthlyLimit;

    @Column(name = "daily_usage")
    private Integer dailyUsage = 0;

    @Column(name = "monthly_usage")
    private Integer monthlyUsage = 0;

    @Column(name = "total_usage")
    private Long totalUsage = 0L;

    @Column(name = "expiry_time")
    private LocalDateTime expiresAt;

    @Column(name = "user_id", nullable = false, length = 50)
    private String userId;

    @Column(name = "operator_id", length = 50)
    private String operatorId;

    @Column(name = "operation_type", length = 20)
    private String operationType;

    @Column(name = "description", columnDefinition = "TEXT")
    private String description;

    @Column(name = "created_time", nullable = false)
    private LocalDateTime createdAt;

    @Column(name = "updated_time", nullable = false)
    private LocalDateTime updatedAt;

    @Column(name = "is_deleted", nullable = false)
    private Boolean isDeleted = false;

    @Column(name = "last_used_at")
    private LocalDateTime lastUsedAt;

    @Column(name = "application_id")
    private Long applicationId;

    /**
     * 默认构造函数
     */
    public ApiKey() {
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 构造函数
     *
     * @param name     API Key名称
     * @param keyValue API Key值
     * @param userId   用户ID
     */
    public ApiKey(String name, String keyValue, String userId) {
        this();
        this.name = name;
        this.keyValue = keyValue;
        this.userId = userId;
    }

    // Getter和Setter方法

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getKeyValue() {
        return keyValue;
    }

    public void setKeyValue(String keyValue) {
        this.keyValue = keyValue;
    }

    public String getPermissions() {
        return permissions;
    }

    public void setPermissions(String permissions) {
        this.permissions = permissions;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Integer getDailyLimit() {
        return dailyLimit;
    }

    public void setDailyLimit(Integer dailyLimit) {
        this.dailyLimit = dailyLimit;
    }

    public Integer getMonthlyLimit() {
        return monthlyLimit;
    }

    public void setMonthlyLimit(Integer monthlyLimit) {
        this.monthlyLimit = monthlyLimit;
    }

    public Integer getDailyUsage() {
        return dailyUsage;
    }

    public void setDailyUsage(Integer dailyUsage) {
        this.dailyUsage = dailyUsage;
    }

    public Integer getMonthlyUsage() {
        return monthlyUsage;
    }

    public void setMonthlyUsage(Integer monthlyUsage) {
        this.monthlyUsage = monthlyUsage;
    }

    public Long getTotalUsage() {
        return totalUsage;
    }

    public void setTotalUsage(Long totalUsage) {
        this.totalUsage = totalUsage;
    }

    public LocalDateTime getExpiresAt() {
        return expiresAt;
    }

    public void setExpiresAt(LocalDateTime expiresAt) {
        this.expiresAt = expiresAt;
    }

    public LocalDateTime getExpiryTime() {
        return expiresAt;
    }

    public void setExpiryTime(LocalDateTime expiryTime) {
        this.expiresAt = expiryTime;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getOperatorId() {
        return operatorId;
    }

    public void setOperatorId(String operatorId) {
        this.operatorId = operatorId;
    }

    public String getOperationType() {
        return operationType;
    }

    public void setOperationType(String operationType) {
        this.operationType = operationType;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }

    public Boolean getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(Boolean isDeleted) {
        this.isDeleted = isDeleted;
    }

    /**
     * 获取最后使用时间
     *
     * @return 最后使用时间
     */
    public LocalDateTime getLastUsedAt() {
        return lastUsedAt;
    }

    /**
     * 设置最后使用时间
     *
     * @param lastUsedAt 最后使用时间
     */
    public void setLastUsedAt(LocalDateTime lastUsedAt) {
        this.lastUsedAt = lastUsedAt;
    }

    /**
     * 获取关联申请记录ID
     *
     * @return 申请记录ID
     */
    public Long getApplicationId() {
        return applicationId;
    }

    /**
     * 设置关联申请记录ID
     *
     * @param applicationId 申请记录ID
     */
    public void setApplicationId(Long applicationId) {
        this.applicationId = applicationId;
    }

    /**
     * 更新时间戳
     */
    @PreUpdate
    public void preUpdate() {
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 检查API Key是否已过期
     *
     * @return 是否已过期
     */
    public boolean isExpired() {
        return expiresAt != null && LocalDateTime.now().isAfter(expiresAt);
    }

    /**
     * 检查API Key是否处于活跃状态
     *
     * @return 是否活跃
     */
    public boolean isActive() {
        return "ACTIVE".equals(status) && !isExpired() && !isDeleted;
    }

    /**
     * 增加使用次数
     */
    public void incrementUsage() {
        if (this.dailyUsage == null) {
            this.dailyUsage = 0;
        }
        if (this.monthlyUsage == null) {
            this.monthlyUsage = 0;
        }
        if (this.totalUsage == null) {
            this.totalUsage = 0L;
        }

        this.dailyUsage++;
        this.monthlyUsage++;
        this.totalUsage++;
    }

    /**
     * 检查是否超出每日限制
     *
     * @return 是否超出限制
     */
    public boolean isDailyLimitExceeded() {
        return dailyLimit != null && dailyUsage != null && dailyUsage >= dailyLimit;
    }

    /**
     * 检查是否超出每月限制
     *
     * @return 是否超出限制
     */
    public boolean isMonthlyLimitExceeded() {
        return monthlyLimit != null && monthlyUsage != null && monthlyUsage >= monthlyLimit;
    }

    /**
     * 检查是否超出使用限制
     *
     * @return 是否超出限制
     */
    public boolean isOverLimit() {
        return isDailyLimitExceeded() || isMonthlyLimitExceeded();
    }

    /**
     * 获取总限制
     *
     * @return 总限制
     */
    public Long getTotalLimit() {
        // 返回总使用限制，如果没有设置则返回null
        return null;
    }

    /**
     * 标记为已删除
     */
    public void markAsDeleted() {
        this.isDeleted = true;
        this.updatedAt = LocalDateTime.now();
    }

    @Override
    public String toString() {
        return "ApiKey{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", keyValue='" + keyValue + '\'' +
                ", status='" + status + '\'' +
                ", userId='" + userId + '\'' +
                ", createdAt=" + createdAt +
                ", isDeleted=" + isDeleted +
                '}';
    }
}